import { FC, ReactNode, Children, ChangeEvent, useContext, MouseEvent, useRef } from 'react';
import styles from './styles.module.less';
import { ReactEditor } from 'slate-react';
import { Editor, Node, Transforms } from 'slate';
import { PLUGINS_KEYS } from '../types';
import { appContext } from '@/config/context';
import { createPortal } from 'react-dom';

interface IProps {
  children: ReactNode;
  language?: string;
  element: Node;
  editor: Editor;
}
interface ITEMIProps {
  children: ReactNode;
}
const CodeBlockItem: FC<ITEMIProps> = ({ children }) => {
  return <div className={styles['code-block-item']}>{children}</div>;
};

const CodeBlock: FC<IProps> = ({ children, language, editor, element }) => {
  const toobarHover = useRef<HTMLDivElement | null>(null);
  const { readonly } = useContext(appContext);

  const onChange = (e: ChangeEvent<HTMLSelectElement>) => {
    const value = e.target.value;
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    if (!Editor.isBlock(editor, element)) throw new Error('Element is not Node');
    // 查找指定 node 节点的 Path
    const path = ReactEditor.findPath(editor, element);
    Transforms.setNodes(
      editor,
      {
        [PLUGINS_KEYS.CODEBLOCK]: {
          language: value,
        },
      },
      {
        at: path,
      }
    );
  };
  const onMouseEnter = (event: MouseEvent<HTMLDivElement>) => {
    const target = event.currentTarget;
    const rect = target.getBoundingClientRect();

    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
    const toobar = toobarHover.current!;
    toobar.style.setProperty('display', 'block');
    toobar.style.setProperty('top', rect.y - toobar.clientHeight + 'px');
  };
  const onMouseLeave = () => {
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
    const toobar = toobarHover.current!;
    toobar.style.setProperty('display', 'none');
  };
  return (
    <div id="code-block" className={styles['code-block']} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
      {Children.map(children, (child) => {
        return <CodeBlockItem>{child}</CodeBlockItem>;
      })}
      {!readonly &&
        createPortal(
          <div className={styles['code-block-hover']} ref={toobarHover}>
            <div className={styles['hover-content']}>
              <select value={language?.toLocaleLowerCase()} onChange={onChange}>
                <option value="javascript">javascript</option>
                <option value="java">java</option>
              </select>
              <i className={styles.driver} />
              <div>
                自动换行 <button>OK?(待支持)</button>
              </div>
            </div>
          </div>,
          document.body
        )}
    </div>
  );
};

export default CodeBlock;
